/**
 * @file EventLoop.hpp
 * @brief 事件循环类的声明
 * @details 基于epoll的事件循环，负责监听和分发IO事件
 */

#ifndef __EventLoop_HPP__
#define __EventLoop_HPP__
#include "TcpConnection.hpp"
#include "MutexLock.hpp"
#include "logger.hpp"

#include <sys/epoll.h>
#include <sys/eventfd.h>
#include <vector>
#include <map>

using std::vector;
using std::map;

namespace wd
{

using Functor=std::function<void()>;
class Acceptor;

/**
 * @class EventLoop
 * @brief 事件循环类
 * @details 封装了epoll的IO多路复用机制，处理新连接和消息读写事件
 */
class EventLoop
{
public:
    /**
     * @brief 构造函数
     * @param ac Acceptor引用，用于接受新连接
     * @param mylogger 日志对象引用
     */
    EventLoop(Acceptor & ac,MyLogger &mylogger);
    ~EventLoop();

    /**
     * @brief 启动事件循环
     */
    void loop();
    
    /**
     * @brief 停止事件循环
     */
    void unloop() { _isLooping = false; }
    
    /**
     * @brief 在事件循环中运行函数对象
     * @param f 要执行的函数对象
     */
    void runInLoop(Functor && f);
    
    /**
     * @brief 注册三个回调函数
     * @param cb1 连接建立回调
     * @param cb2 消息到达回调
     * @param cb3 连接关闭回调
     */
    void setAllCallbacks(TcpConnectionCallback && cb1,
                         TcpConnectionCallback && cb2,
                         TcpConnectionCallback && cb3)
    {
        _onConnection = std::move(cb1);
        _onMessage = std::move(cb2);
        _onClose = std::move(cb3);
    }

private:
    /**
     * @brief 创建epoll文件描述符
     * @return epoll文件描述符
     */
    int createEpollFd();
    
    /**
     * @brief 将文件描述符添加到epoll监听（读事件）
     * @param fd 要添加的文件描述符
     */
    void addEpollReadEvent(int fd);
    
    /**
     * @brief 从epoll中删除文件描述符
     * @param fd 要删除的文件描述符
     */
    void delEpollReadEvent(int fd);

    /**
     * @brief 等待epoll事件
     */
    void waitEpollFd();
    
    /**
     * @brief 处理新连接事件
     */
    void handleNewConnection();
    
    /**
     * @brief 处理消息事件
     * @param fd 触发事件的文件描述符
     */
    void handleMessage(int);

    /**
     * @brief 创建eventfd用于线程间通信
     * @return eventfd文件描述符
     */
    int createEventFd();
    
    /**
     * @brief 唤醒事件循环
     */
    void wakeup();
    
    /**
     * @brief 处理eventfd的读事件
     */
    void handleRead();
    
    /**
     * @brief 执行待处理的函数对象
     */
    void doPendingFunctors();

private:
    int _epfd;                                  ///< epoll文件描述符
    int _eventfd;                               ///< eventfd用于唤醒
    Acceptor & _acceptor;                       ///< 连接接受器引用
    MyLogger & _mylogger;                       ///< 日志对象引用
    bool _isLooping;                            ///< 循环标志
    vector<struct epoll_event> _evtArr;         ///< epoll事件数组
    map<int, TcpConnectionPtr> _conns;          ///< 连接映射表
    TcpConnectionCallback _onConnection;        ///< 连接建立回调
    TcpConnectionCallback _onMessage;           ///< 消息到达回调
    TcpConnectionCallback _onClose;             ///< 连接关闭回调
    vector<Functor> _pendingFunctors;           ///< 待处理的函数对象
    MutexLock       _mutex;                     ///< 互斥锁
};

}//end of namespace wd


#endif

